<template>
  <div class="network-monitor">
    <div class="monitor-controls">
      <button class="btn primary" @click="startMonitoring" :disabled="isMonitoring">
        <i class="icon-start"></i>
        开始监控
      </button>
      <button class="btn danger" @click="stopMonitoring" :disabled="!isMonitoring">
        <i class="icon-stop"></i>
        停止监控
      </button>
      <button class="btn secondary" @click="clearLogs">
        <i class="icon-clear"></i>
        清空记录
      </button>
    </div>

    <div class="network-filters">
      <div class="filter-group">
        <label>请求类型</label>
        <div class="checkbox-group">
          <label v-for="type in requestTypes" :key="type">
            <input type="checkbox" v-model="selectedTypes" :value="type">
            <span class="checkbox-custom"></span>
            {{ type }}
          </label>
        </div>
      </div>
      <div class="filter-group">
        <label>状态码</label>
        <input type="text" v-model="statusFilter" placeholder="例如: 200,404">
      </div>
    </div>

    <div class="network-table">
      <div class="table-header">
        <div class="col method">方法</div>
        <div class="col url">URL</div>
        <div class="col status">状态</div>
        <div class="col size">大小</div>
        <div class="col time">时间</div>
      </div>
      <div class="table-body" ref="tableBody">
        <div
            v-for="(request, index) in filteredRequests"
            :key="index"
            :class="['table-row', request.statusClass]"
            @click="selectRequest(index)"
        >
          <div class="col method">{{ request.method }}</div>
          <div class="col url">{{ request.url }}</div>
          <div class="col status">{{ request.status }}</div>
          <div class="col size">{{ formatSize(request.size) }}</div>
          <div class="col time">{{ request.time }}ms</div>
        </div>
      </div>
    </div>

    <div class="request-details" v-if="selectedRequest">
      <h3>请求详情</h3>
      <div class="detail-tabs">
        <button
            v-for="tab in detailTabs"
            :key="tab"
            :class="['tab-button', { 'active': activeDetailTab === tab }]"
            @click="activeDetailTab = tab"
        >
          {{ tab }}
        </button>
      </div>

      <div class="detail-content">
        <div v-if="activeDetailTab === 'Headers'">
          <pre>{{ selectedRequest.headers }}</pre>
        </div>
        <div v-if="activeDetailTab === 'Payload'">
          <pre>{{ selectedRequest.payload }}</pre>
        </div>
        <div v-if="activeDetailTab === 'Response'">
          <pre>{{ selectedRequest.response }}</pre>
        </div>
        <div v-if="activeDetailTab === 'Timing'">
          <div class="timing-chart">
            <div class="timing-bar">
              <div
                  class="timing-segment dns"
                  :style="{ width: `${selectedRequest.timing.dns}%` }"
              >DNS: {{ selectedRequest.timing.dnsTime }}ms</div>
              <div
                  class="timing-segment tcp"
                  :style="{ width: `${selectedRequest.timing.tcp}%` }"
              >TCP: {{ selectedRequest.timing.tcpTime }}ms</div>
              <div
                  class="timing-segment request"
                  :style="{ width: `${selectedRequest.timing.request}%` }"
              >请求: {{ selectedRequest.timing.requestTime }}ms</div>
              <div
                  class="timing-segment response"
                  :style="{ width: `${selectedRequest.timing.response}%` }"
              >响应: {{ selectedRequest.timing.responseTime }}ms</div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import { ref, computed, onBeforeUnmount } from 'vue'

export default {
  name: 'NetworkMonitor',
  setup() {
    const isMonitoring = ref(false)
    const requests = ref([])
    const selectedRequest = ref(null)
    const selectedTypes = ref(['GET', 'POST', 'PUT', 'DELETE'])
    const statusFilter = ref('')
    const activeDetailTab = ref('Headers')
    const tableBody = ref(null)

    const requestTypes = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS']
    const detailTabs = ['Headers', 'Payload', 'Response', 'Timing']

    // 过滤后的请求列表
    const filteredRequests = computed(() => {
      return requests.value.filter(request => {
        const typeMatch = selectedTypes.value.includes(request.method)
        const statusMatch = statusFilter.value
            ? statusFilter.value.split(',').includes(request.status.toString())
            : true
        return typeMatch && statusMatch
      })
    })

    // 开始监控
    const startMonitoring = () => {
      isMonitoring.value = true
      requests.value = []

      // 模拟网络请求监控
      window.mockNetworkRequests = setInterval(() => {
        addMockRequest()
      }, 1500)
    }

    // 停止监控
    const stopMonitoring = () => {
      isMonitoring.value = false
      clearInterval(window.mockNetworkRequests)
    }

    // 清空记录
    const clearLogs = () => {
      requests.value = []
      selectedRequest.value = null
    }

    // 选择请求
    const selectRequest = (index) => {
      selectedRequest.value = filteredRequests.value[index]
      activeDetailTab.value = 'Headers'
    }

    // 格式化大小
    const formatSize = (bytes) => {
      if (bytes === 0) return '0 B'
      const k = 1024
      const sizes = ['B', 'KB', 'MB', 'GB']
      const i = Math.floor(Math.log(bytes) / Math.log(k))
      return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]
    }

    // 添加模拟请求
    const addMockRequest = () => {
      const methods = ['GET', 'POST', 'PUT', 'DELETE']
      const statusCodes = [200, 201, 400, 401, 404, 500]
      const urls = [
        '/api/users',
        '/api/posts',
        '/api/comments',
        '/api/settings',
        '/api/auth/login'
      ]

      const method = methods[Math.floor(Math.random() * methods.length)]
      const status = statusCodes[Math.floor(Math.random() * statusCodes.length)]
      const url = urls[Math.floor(Math.random() * urls.length)]

      const timing = {
        dns: Math.random() * 10,
        dnsTime: Math.floor(Math.random() * 50),
        tcp: Math.random() * 15,
        tcpTime: Math.floor(Math.random() * 100),
        request: Math.random() * 30,
        requestTime: Math.floor(Math.random() * 200),
        response: Math.random() * 45,
        responseTime: Math.floor(Math.random() * 300)
      }

      const totalTime = timing.dnsTime + timing.tcpTime + timing.requestTime + timing.responseTime

      const request = {
        method,
        url,
        status,
        size: Math.floor(Math.random() * 1024 * 1024),
        time: totalTime,
        timing,
        statusClass: status >= 400 ? 'error' : status >= 300 ? 'redirect' : 'success',
        headers: {
          'Content-Type': 'application/json',
          'Authorization': 'Bearer xyz123',
          'Accept': '*/*'
        },
        payload: method === 'GET' ? null : { id: Date.now(), data: 'sample payload' },
        response: {
          status,
          data: { message: `${method} request to ${url} completed` }
        }
      }

      requests.value.unshift(request)
    }

    onBeforeUnmount(() => {
      stopMonitoring()
    })

    return {
      isMonitoring,
      requests,
      selectedRequest,
      selectedTypes,
      statusFilter,
      activeDetailTab,
      tableBody,
      requestTypes,
      detailTabs,
      filteredRequests,
      startMonitoring,
      stopMonitoring,
      clearLogs,
      selectRequest,
      formatSize
    }
  }
}
</script>

<style scoped>
.network-monitor {
  height: 100%;
  display: flex;
  flex-direction: column;
  padding: 15px;
}

.monitor-controls {
  display: flex;
  gap: 10px;
  margin-bottom: 15px;
}

.network-filters {
  display: flex;
  gap: 20px;
  margin-bottom: 15px;
  padding-bottom: 15px;
  border-bottom: 1px solid var(--border-color);
}

.filter-group {
  display: flex;
  align-items: center;
  gap: 10px;
}

.checkbox-group {
  display: flex;
  gap: 15px;
}

.checkbox-group label {
  display: flex;
  align-items: center;
  cursor: pointer;
  font-size: 0.9rem;
}

.checkbox-group input[type="checkbox"] {
  position: absolute;
  opacity: 0;
}

.checkbox-custom {
  width: 16px;
  height: 16px;
  border: 2px solid var(--border-color);
  border-radius: 3px;
  margin-right: 8px;
  position: relative;
  transition: var(--transition);
}

.checkbox-group input:checked + .checkbox-custom {
  background-color: var(--primary-color);
  border-color: var(--primary-color);
}

.checkbox-group input:checked + .checkbox-custom::after {
  content: '';
  position: absolute;
  left: 4px;
  top: 1px;
  width: 4px;
  height: 8px;
  border: solid white;
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}

.network-table {
  flex: 1;
  display: flex;
  flex-direction: column;
  border: 1px solid var(--border-color);
  border-radius: 8px;
  overflow: hidden;
}

.table-header, .table-row {
  display: flex;
  padding: 10px 15px;
}

.table-header {
  background: rgba(0, 0, 0, 0.3);
  font-weight: 500;
}

.table-body {
  flex: 1;
  overflow-y: auto;
}

.table-row {
  border-bottom: 1px solid var(--border-color);
  cursor: pointer;
  transition: var(--transition);
}

.table-row:hover {
  background: rgba(255, 255, 255, 0.05);
}

.table-row.success {
  background: rgba(0, 255, 135, 0.05);
}

.table-row.redirect {
  background: rgba(255, 215, 0, 0.05);
}

.table-row.error {
  background: rgba(255, 31, 113, 0.05);
}

.col {
  flex: 1;
}

.col.method {
  flex: 0.5;
  text-transform: uppercase;
}

.col.status {
  flex: 0.5;
}

.col.size {
  flex: 0.5;
  text-align: right;
}

.col.time {
  flex: 0.5;
  text-align: right;
}

.request-details {
  margin-top: 15px;
  background: rgba(0, 0, 0, 0.2);
  border-radius: 8px;
  padding: 15px;
}

.detail-tabs {
  display: flex;
  border-bottom: 1px solid var(--border-color);
  margin-bottom: 15px;
}

.detail-tabs .tab-button {
  padding: 8px 15px;
  background: none;
  border: none;
  color: var(--text-secondary);
  cursor: pointer;
  border-bottom: 2px solid transparent;
}

.detail-tabs .tab-button.active {
  color: var(--primary-color);
  border-bottom-color: var(--primary-color);
}

.detail-content pre {
  background: rgba(0, 0, 0, 0.3);
  padding: 10px;
  border-radius: 4px;
  overflow-x: auto;
  font-family: 'Fira Code', monospace;
  font-size: 0.85rem;
}

.timing-chart {
  margin-top: 15px;
}

.timing-bar {
  display: flex;
  height: 30px;
  background: rgba(255, 255, 255, 0.1);
  border-radius: 4px;
  overflow: hidden;
}

.timing-segment {
  display: flex;
  align-items: center;
  justify-content: center;
  color: white;
  font-size: 0.7rem;
  font-weight: bold;
  height: 100%;
}

.timing-segment.dns {
  background: var(--accent-color);
}

.timing-segment.tcp {
  background: var(--primary-color);
}

.timing-segment.request {
  background: var(--warning-color);
}

.timing-segment.response {
  background: var(--secondary-color);
}

.icon-start,
.icon-stop,
.icon-clear {
  display: inline-block;
  width: 16px;
  height: 16px;
  background-size: contain;
  background-repeat: no-repeat;
  background-position: center;
}

.icon-start {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24' stroke='%23ffffff'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M14.752 11.168l-3.197-2.132A1 1 0 0010 9.87v4.263a1 1 0 001.555.832l3.197-2.132a1 1 0 000-1.664z' /%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M21 12a9 9 0 11-18 0 9 9 0 0118 0z' /%3E%3C/svg%3E");
}

.icon-stop {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24' stroke='%23ffffff'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M21 12a9 9 0 11-18 0 9 9 0 0118 0z' /%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M9 10a1 1 0 011-1h4a1 1 0 011 1v4a1 1 0 01-1 1h-4a1 1 0 01-1-1v-4z' /%3E%3C/svg%3E");
}

.icon-clear {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24' stroke='%23ffffff'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16' /%3E%3C/svg%3E");
}
</style>
